#ifndef NODE_H
#define NODE_H
#include <map>
#include <queue>
#include <set>
#include "GrammarSymbol.h"
#include "Production.h"

enum Item_Category {
    CORE,       // 核心项
    NONCORE     // 非核心项
};

class LR0Item {
public:
    NonTerminalSymbol *non_terminal_symbol;     // 非终结符
    PRO_ID production_id;                       // 产生式
    int dot_position;                             // 圆点位置
    Item_Category type;

    // 比较函数，用于 std::set
    bool operator<(const LR0Item& other) const {
        if (non_terminal_symbol != other.non_terminal_symbol)
            return non_terminal_symbol < other.non_terminal_symbol;
        if (production_id != other.production_id)
            return production_id < other.production_id;
        if (dot_position != other.dot_position)
            return dot_position < other.dot_position;
        return type < other.type;
    }

    LR0Item(NonTerminalSymbol* sym,PRO_ID id,int dot,Item_Category type=NONCORE):non_terminal_symbol(sym),production_id(id),dot_position(dot){
        //this->type=CORE;
        if(Production::get_epsilo_production_id()==id){
            this->dot_position=0;
            
        }else{
            int lt_size=Production::get_production_body_symbol_table(id).size();
            assert(dot<=lt_size);
            
        }
    }

    bool judge_final_item(){
        //判断当前是不是处于需要规约的状态，点在production的末端 E-> T.这样的
        int lt_size=Production::get_production_body_symbol_table(production_id).size();
        return lt_size==dot_position;
    }

    GrammarSymbol *get_excepted_symbol(){
        auto lst=Production::get_production_body_symbol_table(production_id);
        if(dot_position==lst.size()){
            return (GrammarSymbol*)(nullptr);
        }else{
            auto it=lst.begin();
            int temp_dot=dot_position;
            while(temp_dot--){
                it++;
            }
            return (*it);
        }
    }


    string get_info(){
        string res=non_terminal_symbol->name;
        res += " -> ";
        if(production_id==Production::get_epsilo_production_id()){
            res+=".";
            return res;
        }
        auto list_grammar=move(Production::get_production_body_symbol_table(production_id));
        auto it=list_grammar.begin();
        for(int i=0;i<list_grammar.size();i++,it++){
            if(i==dot_position){
                res +=".";
            }
            res+=(*it)->name;
        }
        if(dot_position==list_grammar.size()){
            res+=".";
        }
        if(type==CORE){
            res+="\t\tCORE";
        }
        return res;
    }
};


class ActionCell {
public:
    int from_state_id=-1;                                   // 状态序号
    std::string terminal_symbol_name;              // 终结符名
    enum Action_Category {
        REDUCE,     // 规约
        SHIFT,      // 移进
        ACCEPT      // 接受
    } type;
    int to_state_id;                                         // 产生式序号

    ActionCell(){}

    ActionCell(int fr,int to,string name,Action_Category action):
        from_state_id(fr),to_state_id(to),terminal_symbol_name(name),type(action){}

    string get_info(){
        if(from_state_id==-1){
            return "    ";//失败
        }else{
            switch (type)
            {
            case REDUCE:
                return "reduce "+to_string(to_state_id);
            case SHIFT:
                return "shift "+to_string(to_state_id);
            case ACCEPT:
                return "accept";
            default:
                return "    ";
            }
        }
    }
};

class GotoCell {
public:
    int from_state_id=-1;                                   // 状态序号
    std::string non_terminal_symbol_name;          // 非终结符名
    int to_state_id;                              // 下一个状态序号
    GotoCell(){

    }

    GotoCell(int fr,int to,string name):
        from_state_id(fr),to_state_id(to),non_terminal_symbol_name(name){}
    
    string get_info(){
        if(from_state_id==-1){
            return "    ";//失败
        }else{
            return to_string(to_state_id);
        }
    }

};

class DFANode {
public:
    int state_id;                                  // 状态序号
    std::set<LR0Item> item_table;              // 项表
    std::map<GrammarSymbol*,int> transition;    //转换表
    std::map<TerminalSymbol*,int> reduce_mp;     //规约表 
    DFANode(int id=-1){
        this->state_id=id;
    }

    DFANode(int id,LR0Item ptr){
        ptr.type=CORE;
        this->state_id=id;
        add_item(ptr);
    }

    void add_item(LR0Item ptr){
        //加入一个item，包括求他的关系闭包
        if(!item_table.count(ptr)){
            //这里一定要判断是否添加过，不然会左递归，死循环
            item_table.insert(ptr);
            if(ptr.judge_final_item()){
                for(auto &terminal:ptr.non_terminal_symbol->follow_set){
                    reduce_mp[terminal]=ptr.production_id;
                }
            }
            auto next_symbol=ptr.get_excepted_symbol();
            if(next_symbol!=nullptr&&next_symbol->type==NON_TERMINAL){

                NonTerminalSymbol* next_non_terminal=static_cast<NonTerminalSymbol*>(next_symbol);
                for(auto production_id:next_non_terminal->production_table){
                    this->add_item(LR0Item(next_non_terminal,production_id,0));
                }
                
            }
        }

    };

    void get_info(){
        cout<<"state id : "<<state_id<<endl;
        for(auto elem:item_table){
            cout<<elem.get_info()<<endl;
        }cout<<endl;
        if(transition.size()==0){
            cout<<"no transitions\n\n";
            return;
        }
        cout<<"transitions : input --> next state id"<<endl;
        for(auto elem:transition){
            cout<<elem.first->get_name()<< "  -->  "<<elem.second<<endl;
        }
        cout<<endl;
    }


};



#endif